unit FeedingCategoryTable;

{$mode objfpc}{$H+}

//========================================================================================
//
// Unit : FeedingCategoryTable.pas
//
// Description : This module maintains the Feeding Category table that is used by all
//               Tank projects. It Creates the table when the progam is first launceh,
//               with initial default Categories and provides functionality to add
//               additional categories as required.
//
// Calls : FeedingCategoryRecord : ProcessRecord
//
// Called By :
//
// Ver. : 1.0.0
//
// Date : 2 Oct 2016
//
//========================================================================================

interface

uses
  Classes, SysUtils, db, dbf, FileUtil, Forms, Controls, Graphics, Dialogs,
  Grids, Buttons, DBGrids, DbCtrls, ComCtrls, Menus, StdCtrls,
  // Application Units
  ApplicationSettings, FeedingCategoryRecord;

type

  { TfrmFeedingCategoryTable }

  TfrmFeedingCategoryTable = class(TForm)
    bbtHelp: TBitBtn;
    bbtClose: TBitBtn;
    dbfFeedingCategoryTable: TDbf;
    dbgFeedingCategoryTable: TDBGrid;
    dsFeedingCategoryTable: TDataSource;
    pumDeleteCategory: TMenuItem;
    pumEditCategory: TMenuItem;
    pumAddCategory: TMenuItem;
    pumDBRecord: TPopupMenu;
    StaticText1: TStaticText;
    StatusBar1: TStatusBar;
    procedure bbtCloseClick(Sender: TObject);
    procedure bbtHelpClick(Sender: TObject);
    procedure dbgFeedingCategoryTableMouseUp(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure dsFeedingCategoryTableStateChange(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormShow(Sender: TObject);
    procedure pumAddCategoryClick(Sender: TObject);
    procedure pumEditCategoryClick(Sender: TObject);
    procedure pumDeleteCategoryClick(Sender: TObject);
  private
    { private declarations }
    procedure SetupFeedingCategoryTable;
  public
    { public declarations }
    function CreateFeedingCategoryTable: boolean;
    function GetCurrentRecord: TFeedingCategoryRecord;
  end;

const
  cbytFeedingCategoryIDLength = 1;
  cstrMinFeedingCategpryIID = 1;
  cstrMaxFeedingCategoryID = 9;

  cintFeedingCategoryCarnivoreID = 1;
  cintFeedingCategoryHerbivoreID = 2;
  cintFeedingCategoryOtherID = cstrMaxFeedingCategoryID;

  cbytFeedingCategoryActiveLength = 1;
  cblnFeedingCategoryActive = True;
  cblnFeedingCategoryInActive = False;

  cbytMinFeedingCategoryLength = 3;
  cbytMaxFeedingCategoryLength = 15;

  // Form
  cstrfrmFeedintCategoryTableName = 'Feeding Category Table';

  // Data Table
  cstrFeedingCategoryTableName = 'FeedingCategoryTable.dbf';

  cstrFeedingCategoryID = 'ID';
  cstrFeedingCategoryActive = 'Active';
  cstrFeedingCategory = 'Category';

  cstrFeedingCategoryCarnivore = 'Carnivore';
  cstrFeedingCategoryHerbivore = 'Herbivore';
  cstrFeedingCategoryOther = 'Other';

  cstrFeedingCategoryIDIndex = 'FeedingCategoryID';
  cstrFeedingCategoryIndex = 'FeedingCategory';

var
  frmFeedingCategoryTable: TfrmFeedingCategoryTable;

implementation

{$R *.lfm}

const

  cstrUsageMessage = 'The Left and Right mouse buttons and the <PgUp> and <PgDn> keys' +
                     'are used to select the desired Category.' +
                     #13 + #13 +
                     'The Right mouse button will display a small menu list that will' +
                     'provide the capability to Add a New Category, Edit the selected' +
                     ' Category or Cancel the operation.';

//========================================================================================
//          PRIVATE ROUTINES
//========================================================================================
procedure TfrmFeedingCategoryTable.dsFeedingCategoryTableStateChange(
  Sender: TObject);
begin

end;// procedure TfrmFeedingCategoryTable.dsFeedingCategoryTableStateChange

//========================================================================================
procedure TfrmFeedingCategoryTable.SetupFeedingCategoryTable;
begin

{  dbfFeedingCategoryTable.FilePath := frmSettings.ApplicationDataPath;
  dbfFeedingCategoryTable.TableName := cstrFeedingCategoryTableName;
  dbfFeedingCategoryTable.Exclusive := True;   }

end;// procedure TfrmFeedingCategoryTable.SetupFeedingCategoryTable

//========================================================================================
//          PUBLIC ROUTINES
//========================================================================================
function TfrmFeedingCategoryTable.CreateFeedingCategoryTable: boolean;
begin

  // Configure the Data Table
  SetupFeedingCategoryTable;

  // Add the Fields
  dbfFeedingCategoryTable.FieldDefs.Add(cstrFeedingCategoryID,
                                         ftInteger,
                                         cbytFeedingCategoryIDLength,
                                         True);
  dbfFeedingCategoryTable.FieldDefs.Add(cstrFeedingCategory,
                                         ftString,
                                         cbytMaxFeedingCategoryLength,
                                         True);
  dbfFeedingCategoryTable.FieldDefs.Add(cstrFeedingCategoryActive,
                                         ftBoolean,
                                         cbytFeedingCategoryActiveLength,
                                         True);

  //Create the Table and Indexes
  dbfFeedingCategoryTable.TableLevel := 7;
  dbfFeedingCategoryTable.CreateTable;
  dbfFeedingCategoryTable.Active := True;

  dbfFeedingCategoryTable.AddIndex (cstrFeedingCategoryIDIndex,
                                   cstrFeedingCategoryID,
                                   [ixPrimary, ixUnique]);
  dbfFeedingCategoryTable.AddIndex (cstrFeedingCategoryIndex,
                                   cstrFeedingCategory, [ixUnique]);

  // Add the Data Items
  dbfFeedingCategoryTable.First;
  dbfFeedingCategoryTable.Insert;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryID).AsInteger :=
                                                        cintFeedingCategoryCarnivoreID;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategory).AsString :=
                                                        cstrFeedingCategoryCarnivore;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryActive).AsBoolean :=
                                                        cblnFeedingCategoryActive;

  dbfFeedingCategoryTable.Next;
  dbfFeedingCategoryTable.Insert;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryID).AsInteger :=
                                                        cintFeedingCategoryHerbivoreID;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategory).AsString :=
                                                        cstrFeedingCategoryHerbivore;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryActive).AsBoolean :=
                                                        cblnFeedingCategoryActive;

  dbfFeedingCategoryTable.Next;
  dbfFeedingCategoryTable.Insert;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryID).AsInteger :=
                                                        cintFeedingCategoryOtherID;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategory).AsString :=
                                                        cstrFeedingCategoryOther;
  dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryActive).AsBoolean :=
                                                        cblnFeedingCategoryActive;

  dbfFeedingCategoryTable.Post;
  dbfFeedingCategoryTable.Active := False;

end;// function TfrmFeedingCategoryTable.CreateFeedingCategoryTable

//========================================================================================
function TfrmFeedingCategoryTable.GetCurrentRecord: TFeedingCategoryRecord;
var
  CurrentRecord: TFeedingCategoryRecord;

begin
  CurrentRecord.CategoryID:=
             dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryID).AsInteger;
  CurrentRecord.Category:=
             dbfFeedingCategoryTable.FieldByName(cstrFeedingCategory).AsString ;
  CurrentRecord.ActiveState:=
             dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryActive).AsBoolean ;
  Result := CurrentRecord;
end;// function TfrmFeedingCategoryTable.GetCurrentRecord

//========================================================================================
//          PUBLISHED ROUTINES
//========================================================================================

//========================================================================================
//          PROPERTY ROUTINES
//========================================================================================

//========================================================================================
//          SUPPORT ROUTINES
//========================================================================================

//========================================================================================
//          MENU ROUTINES
//========================================================================================

//========== POPUP MENUS ===================================================================
procedure TfrmFeedingCategoryTable.pumAddCategoryClick(Sender: TObject);
var
  recCurrentRecord : TFeedingCategoryRecord;
  vintNextAvailableID : integer;
  vintTInt : Integer;
  vstrTStr : string;
begin

  // First we make sure that there is a slot available for the new record. We do this
  // by going to the last record in the table which is ID 9 (Other) and then backing up
  // one record to get the highest index number + 1. If it is cstrMaxFeedingCategoryID
  // then the table is full (1-9). If not, we can add 1 to it and use it as the next
  // available ID number.

  // First we change the Index to ID
  dbfFeedingCategoryTable.IndexName:=cstrFeedingCategoryIDIndex;

  dbfFeedingCategoryTable.Last;
  dbfFeedingCategoryTable.Prior;
  vintNextAvailableID :=
          dbfFeedingCategoryTable.FieldByName(cstrFeedingCategoryID).AsInteger + 1;
  if vintNextAvailableID >= cstrMaxFeedingCategoryID then
  begin
    showmessage('No Room in Table');
    Exit;
  end;

  // Now we reset the Index to "Category'
  dbfFeedingCategoryTable.IndexName:=cstrFeedingCategoryIndex;

  // We have room for the new record so we Clear the Record fields before processing it
  recCurrentRecord.CategoryID := vintNextAvailableID;
  recCurrentRecord.Category := '';
  recCurrentRecord.ActiveState := True;

  // Now we get the new Data
  if frmFeedingCategoryRecord.ProcessRecord (dsInsert, recCurrentRecord ) then
  begin
    showmessage('Post It');
    dbfFeedingCategoryTable.Insert;
    vintTInt := recCurrentRecord.CategoryID;
    dbfFeedingCategoryTable.FieldByName( cstrFeedingCategoryID).AsInteger :=
                                         recCurrentRecord.CategoryID;
    dbfFeedingCategoryTable.FieldByName( cstrFeedingCategory).AsString :=
                                         recCurrentRecord.Category;
    dbfFeedingCategoryTable.FieldByName( cstrFeedingCategoryActive).AsBoolean :=
                                         recCurrentRecord.ActiveState;
    dbfFeedingCategoryTable.Post;

  end
  else
    showmessage('Ignore It');

end;// procedure TfrmFeedingCategoryTable.pumAddCategoryClick

//----------------------------------------------------------------------------------------
procedure TfrmFeedingCategoryTable.pumEditCategoryClick(Sender: TObject);
var
  recCurrentRecord : TFeedingCategoryRecord;
begin
  recCurrentRecord := GetCurrentRecord;
  frmFeedingCategoryRecord.ProcessRecord (dsEdit, recCurrentRecord );
end;// procedure TfrmFeedingCategoryTable.pumEditCategoryClick

//----------------------------------------------------------------------------------------
procedure TfrmFeedingCategoryTable.pumDeleteCategoryClick(Sender: TObject);
var
  recCurrentRecord : TFeedingCategoryRecord;
begin
  frmFeedingCategoryRecord.ProcessRecord (dsInActive, recCurrentRecord);
end;// procedure TfrmFeedingCategoryTable.pmuDeleteCategoryClick

//========================================================================================
//          TOOLBAR ROUTINES
//========================================================================================

//========================================================================================
//           STATUSBAR ROUTINES
//========================================================================================

//========================================================================================
//          FILE ROUTINES
//========================================================================================

//========================================================================================
//          COMMAND BUTTON ROUTINES
//========================================================================================
procedure TfrmFeedingCategoryTable.bbtCloseClick(Sender: TObject);
begin

end;// procedure TfrmFeedingCategoryTable.bbtOKClick

//----------------------------------------------------------------------------------------
procedure TfrmFeedingCategoryTable.bbtHelpClick(Sender: TObject);
begin

end;// procedure TfrmFeedingCategoryTable.bbtHelpClick

//========================================================================================
//          CONTROL ROUTINES
//========================================================================================

procedure TfrmFeedingCategoryTable.dbgFeedingCategoryTableMouseUp(
  Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbRight then
  begin;
    pumDBRecord.PopUp;
  end;// if Button = mbRight
end;// procedure TfrmFeedingCategoryTable.dbgFeedingCategoryTableMouseUp

//========================================================================================
//          DATABASE ROUTINES
//========================================================================================

//========================================================================================
//          FORM ROUTINES
//========================================================================================
procedure TfrmFeedingCategoryTable.FormShow(Sender: TObject);
  // This routine initializes the form each time it is called. It:
  // 1. Saves the initial state of the table;
  // 2. Sets the initial state of the Command buttons; and,
  // 3. Sets the initial Table Changed state to Fales, indicating that no changes have
  //    been made. This allows us to enable the <Save> button if changes have been made
  //    and determine if we have to reset the table if the <Cancel> button has been
  //    selected and changes have been made.

var
  vstrFrmFeedintCategoryTableTitle : string;

begin

  // Setup the Command Buttons
//   bbtSave.Enabled := False;
//   bbtClose.Enabled := True;
//   bbtHelp.Enabled := False;

// Set up the Table parameters
  SetupFeedingCategoryTable;
  dbfFeedingCategoryTable.IndexName:=cstrFeedingCategoryIndex;
  dbfFeedingCategoryTable.Active:=True;
  dbfFeedingCategoryTable.First;

{  case dsFeedingCategoryTable.State of
    dsBrowse : vstrFrmFeedintCategoryTableTitle := cstrfrmFeedintCategoryTableName +
                                                   ' : BROWSING';
    dsEdit : vstrFrmFeedintCategoryTableTitle := cstrfrmFeedintCategoryTableName +
                                                   ' : EDITING';
    dsInsert : vstrFrmFeedintCategoryTableTitle := cstrfrmFeedintCategoryTableName +
                                                   ' : INSERTING';
    else vstrFrmFeedintCategoryTableTitle := cstrfrmFeedintCategoryTableName +
                                                   ' : OTHER';
  end;// case dsFeedingCategoryTable.State }

  frmFeedingCategoryTable.Caption := cstrfrmFeedintCategoryTableName;
  StaticText1.Caption := cstrUsageMessage;

end;// procedure TfrmFeedingCategoryTable.FormShow

//========================================================================================
procedure TfrmFeedingCategoryTable.FormClose(Sender: TObject;
  var CloseAction: TCloseAction);
begin
  dbfFeedingCategoryTable.Active:=False;
end;// procedure TfrmFeedingCategoryTable.FormClose

//========================================================================================
end.// unit FeedingCaztegoryTable;

